home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cvs / sprite / save / add.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-29  |  7.4 KB  |  294 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Id: add.c,v 1.1 91/07/11 12:57:46 jhh Exp Locker: jhh $";
  3. #endif !lint
  4.  
  5. /*
  6.  *    Copyright (c) 1989, Brian Berliner
  7.  *
  8.  *    You may distribute under the terms of the GNU General Public License
  9.  *    as specified in the README file that comes with the CVS 1.0 kit.
  10.  *
  11.  * Add
  12.  *
  13.  *    Adds a file or directory to the RCS source repository.  For a file,
  14.  *    the entry is marked as "needing to be added" in the user's own
  15.  *    CVS.adm directory, and really added to the repository when it is
  16.  *    committed.  For a directory, it is added at the appropriate place
  17.  *    in the source repository and a CVS.adm directory is generated
  18.  *    within the directory.
  19.  *
  20.  *    The -m option is currently the only supported option.  Some may wish
  21.  *    to supply standard "rcs" options here, but I've found that this
  22.  *    causes more trouble than anything else.
  23.  *
  24.  *    The user files or directories must already exist.  For a directory,
  25.  *    it must not already have a CVS.adm file in it.
  26.  *
  27.  *    An "add" on a file that has been "remove"d but not committed will
  28.  *    cause the file to be resurrected.
  29.  */
  30.  
  31. #include <sys/param.h>
  32. #include "cvs.h"
  33.  
  34. add(argc, argv)
  35.     int argc;
  36.     char *argv[];
  37. {
  38.     char tmp[MAXPATHLEN], message[MAXMESGLEN];
  39.     register int i;
  40.     int c, err = 0;
  41.  
  42.     if (argc == 1 || argc == -1)
  43.     add_usage();
  44.     message[0] = '\0';
  45.     optind = 1;
  46.     while ((c = getopt(argc, argv, "m:")) != -1) {
  47.     switch (c) {
  48.     case 'm':
  49.         if (strlen(optarg) >= sizeof(message)) {
  50.         warn(0, "warning: message too long; truncated!");
  51.         (void) strncpy(message, optarg, sizeof(message));
  52.         message[sizeof(message) - 1] = '\0';
  53.         } else
  54.         (void) strcpy(message, optarg);
  55.         break;
  56.     case '?':
  57.     default:
  58.         add_usage();
  59.         break;
  60.     }
  61.     }
  62.     argc -= optind;
  63.     argv += optind;
  64.     Name_Repository();
  65.     for (i = 0; i < argc; i++) {
  66.     (void) strcpy(User, argv[i]);
  67.     if (isdir(User)) {
  68.         err += add_directory(User);
  69.         continue;
  70.     }
  71.     if (islink(User)) {
  72.         err += add_link(User);
  73.         continue;
  74.     }
  75.     (void) sprintf(tmp, "%s/%s", Repository, User);
  76.     if (isfile(tmp)) {
  77.         if (islink(tmp)) {
  78.         warn(0, "%s already is a symbolic in the repository", User);
  79.         } else if (isdir(tmp)) {
  80.         warn(0, "%s already is a directory in the repository", User);
  81.         }
  82.         err++;
  83.         continue;
  84.     }
  85.     (void) sprintf(Rcs, "%s/%s%s", Repository, User, RCSEXT);
  86.     Version_TS(Rcs, Tag, User);
  87.     if (VN_User[0] == '\0') {
  88.         /*
  89.          * No entry available, TS_Rcs is invalid
  90.          */
  91.         if (VN_Rcs[0] == '\0') {
  92.         /*
  93.          * There is no RCS file either
  94.          */
  95.         if (TS_User[0] == '\0') {
  96.             /*
  97.              * There is no user file either
  98.              */
  99.             warn(0, "nothing known about %s", User);
  100.             err++;
  101.         } else {
  102.             /*
  103.              * There is a user file, so build the entry for it
  104.              */
  105.             if (Build_Entry(message) != 0)
  106.             err++;
  107.         }
  108.         } else {
  109.         /*
  110.          * There is an RCS file already, so somebody else
  111.          * must've added it
  112.          */
  113.         warn(0, "%s added independently by second party", User);
  114.         err++;
  115.         }
  116.     } else if (VN_User[0] == '0' && VN_User[1] == '\0') {
  117.         /*
  118.          * An entry for a new-born file, TS_Rcs is dummy,
  119.          * but that is inappropriate here
  120.          */
  121.         warn(0, "%s has already been entered", User);
  122.         err++;
  123.     } else if (VN_User[0] == '-') {
  124.         /*
  125.          * An entry for a removed file, TS_Rcs is invalid
  126.          */
  127.         if (TS_User[0] == '\0') {
  128.         /*
  129.          * There is no user file (as it should be)
  130.          */
  131.         if (VN_Rcs[0] == '\0') {
  132.             /*
  133.              * There is no RCS file, so somebody else must've
  134.              * removed it from under us
  135.              */
  136.             warn(0, "cannot resurrect %s; RCS file removed by second party",
  137.              User);
  138.             err++;
  139.         } else {
  140.             /*
  141.              * There is an RCS file, so remove the "-" from the
  142.              * version number and restore the file
  143.              */
  144.             (void) strcpy(tmp, VN_User+1);
  145.             (void) strcpy(VN_User, tmp);
  146.             (void) sprintf(tmp, "Resurrected %s", User);
  147.             Register(User, VN_User, tmp);
  148.             if (update(2, argv+i-1) == 0) {
  149.             warn(0, "%s, version %s, resurrected", User, VN_User);
  150.             } else {
  151.             warn(0, "could not resurrect %s", User);
  152.             err++;
  153.             }
  154.         }
  155.         } else {
  156.         /*
  157.          * The user file shouldn't be there
  158.          */
  159.         warn(0, "%s should be removed and is still there", User);
  160.         err++;
  161.         }
  162.     } else {
  163.         /*
  164.          * A normal entry, TS_Rcs is valid, so it must already be there
  165.          */
  166.         warn(0, "%s already exists, with version number %s", User, VN_User);
  167.         err++;
  168.     }
  169.     }
  170.     Entries2Files();            /* update CVS.adm/Files file */
  171.     exit(err);
  172. }
  173.  
  174. /*
  175.  * The specified user file is really a directory.  So, let's make sure that
  176.  * it is created in the RCS source repository, and that the user's
  177.  * directory is updated to include a CVS.adm directory.
  178.  *
  179.  * Returns 1 on failure, 0 on success.
  180.  */
  181. static
  182. add_directory(dir)
  183.     char *dir;
  184. {
  185.     char cwd[MAXPATHLEN], rcsdir[MAXPATHLEN];
  186.     char message[MAXPATHLEN+100];
  187.  
  188.     if (index(dir, '/') != NULL) {
  189.     warn(0, "directory %s not added; must be a direct sub-directory", dir);
  190.     return (1);
  191.     }
  192.     if (strcmp(dir, CVSADM) == 0) {
  193.     warn(0, "cannot add a '%s' directory", CVSADM);
  194.     return (1);
  195.     }
  196.     if (getwd(cwd) == NULL) {
  197.     warn(0, "cannot get working directory: %s", cwd);
  198.     return (1);
  199.     }
  200.     if (chdir(dir) < 0) {
  201.     warn(1, "cannot chdir to %s", dir);
  202.     return (1);
  203.     }
  204.     if (isfile(CVSADM)) {
  205.     warn(0, "%s/%s already exists", dir, CVSADM);
  206.     goto out;
  207.     }
  208.     (void) sprintf(rcsdir, "%s/%s", Repository, dir);
  209.     if (isfile(rcsdir) && (!isdir(rcsdir)) || (islink(rcsdir))) {
  210.     warn(0, "%s is not a directory; %s not added", rcsdir, dir);
  211.     goto out;
  212.     }
  213.     (void) sprintf(message, "Directory %s added to the repository\n", rcsdir);
  214.     if (!isdir(rcsdir)) {
  215.     int omask;
  216.     FILE *fptty;
  217.     char line[MAXLINELEN];
  218.  
  219. #ifdef sprite
  220.     fptty = open_file(getenv("TTY"), "r");
  221. #else
  222.     fptty = open_file("/dev/tty", "r");
  223. #endif
  224.     printf("Add directory %s to the repository (y/n) [n] ? ", rcsdir);
  225.     (void) fflush(stdout);
  226.     if (fgets(line, sizeof(line), fptty) == NULL ||
  227.         (line[0] != 'y' && line[0] != 'Y')) {
  228.         warn(0, "directory %s not added", rcsdir);
  229.         (void) fclose(fptty);
  230.         goto out;
  231.     }
  232.     (void) fclose(fptty);
  233.     omask = umask(2);
  234.     if (mkdir(rcsdir, 0777) < 0) {
  235.         warn(1, "cannot mkdir %s", rcsdir);
  236.         (void) umask(omask);
  237.         goto out;
  238.     }
  239.     (void) umask(omask);
  240.     (void) strcpy(Llist, " - New directory"); /* for title in message */
  241.     Update_Logfile(rcsdir, message);
  242.     }
  243.     Create_Admin(rcsdir, DFLT_RECORD);
  244.     printf("%s", message);
  245. out:
  246.     if (chdir(cwd) < 0)
  247.     error(1, "cannot chdir to %s", cwd);
  248.     return (0);
  249. }
  250.  
  251. /*
  252.  * The specified user file is really a symbolic link.  Add it to the
  253.  * repository.
  254.  * Returns 1 on failure, 0 on success.
  255.  */
  256. static
  257. add_link(link)
  258.     char *link;
  259. {
  260.     char rcslink[MAXPATHLEN];
  261.     char message[MAXPATHLEN+100];
  262.     char dest[MAXPATHLEN];
  263.     int     size;
  264.  
  265.     (void) sprintf(rcslink, "%s/%s", Repository, link);
  266.     if (isfile(rcslink)) {
  267.     (void) sprintf(message, 
  268.         "%s already exists; %s not added\n", rcslink, link);
  269.     goto out;
  270.     }
  271.     size = readlink(link, dest, MAXPATHLEN);
  272.     if (size == -1) {
  273.     warn(1, "cannot read contents of symbolic link %s", link);
  274.     return (0);
  275.     }
  276.     if (symlink(dest, rcslink)) {
  277.     warn(1, "cannot make symbolic link %s", rcslink);
  278.     return (0);
  279.     }
  280.     (void) sprintf(message, "Symbolic link %s added to the repository\n", 
  281.     rcslink);
  282. out:
  283.     printf("%s", message);
  284.     return (0);
  285. }
  286.  
  287. static
  288. add_usage()
  289. {
  290.     (void) fprintf(stderr,
  291.            "%s %s [-m 'message'] files...\n", progname, command);
  292.     exit(1);
  293. }
  294.